/**
 * 
 */
package edu.umd.clip.lm.util;

import java.io.Serializable;
import java.util.*;

/**
 * @author Denis Filimonov <den@cs.umd.edu>
 *
 * Functional programming style lists
 */
public class SimpleList<T> implements Serializable, Iterable<T> {
	private static final long serialVersionUID = 1L;
	private final T head;
	private final SimpleList<T> tail;

	public SimpleList() {
		this.head = null;
		this.tail = null;
	}
	
	/**
	 * @param head
	 * @param tail
	 */
	protected SimpleList(T head, SimpleList<T> tail) {
		this.head = head;
		this.tail = tail;
	}

	public SimpleList<T> add(T payload) {
		return new SimpleList<T>(payload, this);
	}
	
	public T head() {
		return this.head;
	}
	
	public SimpleList<T> tail() {
		return this.tail;
	}
	
	public int length() {
		int len = 0;
		SimpleList<T> t = this.tail; 
		while(t != null) {
			++len;
			t = t.tail;
		}
		return len;
	}
	
	public boolean isEmpty() {
		return tail == null;
	}

	public static class SimpleListIterator<T> implements Iterator<T> {
		private SimpleList<T> list;
		
		private SimpleListIterator(SimpleList<T> list) {
			this.list = list;
		}
		
		/* (non-Javadoc)
		 * @see java.util.Iterator#hasNext()
		 */
		@Override
		public boolean hasNext() {
			return list != null && list.head != null;
		}

		/* (non-Javadoc)
		 * @see java.util.Iterator#next()
		 */
		@Override
		public T next() {
			if (hasNext()) {
				T item = list.head;
				list = list.tail;
				return item;
			}
			throw new NoSuchElementException();
		}

		/* (non-Javadoc)
		 * @see java.util.Iterator#remove()
		 */
		@Override
		public void remove() {
			throw new UnsupportedOperationException();
		}
		
	}
	/* (non-Javadoc)
	 * @see java.lang.Iterable#iterator()
	 */
	@Override
	public Iterator<T> iterator() {
		return new SimpleListIterator<T>(this);
	}
}
